package basic;

public class StaticInnerClassDemo {

    private String outerVariable = "外部非静态成员变量";
    private static String outerStaticVariable = "外部静态成员变量";

    //1.静态变量
    //静态变量是属于类的，而不是属于类创建的对象或实例。
    // 因为静态变量被类的所有实例共用，所以非线程安全的。
    // 通常静态变量还和关键字final一起用，作为所有对象共用的资源或常量。
    // 如果静态变量不是私有的，那么可以通过ClassName.variableName来访问它.
    public static String CONST_STR = "静态变量";

    //2.静态方法
    // 类似于静态变量，静态方法也属于类，不属于实例的。
    // 静态方法只能访问类的静态变量，或调用类的静态方法。
    // 通常静态方法作为工具方法，被其它类使用，而不需要创建类的实例。
    public static void say(String msg){
        System.out.println("静态方法:" + msg);
    }
    //3.静态块
    // 类加载器加载对象时，要执行的一组语句。
    // 它用于初始化静态变量。
    // 通常用于类加载的时候创建静态资源。我们在静态块中不能访问非静态变量。
    // 我们可以在一个类中有多个静态块，尽管这么做没什么意义。静态块只会在类加载到内存中的时候执行一次。
    static {
        System.out.println("静态块");
    }

    public static void main(String[] args) {

        //外部类静态方法中访问内部类，只能访问静态内部类[静态成员，静态内部类]

        System.out.println(StaticInnerClass.staticVariable);
        //System.out.println(StaticInnerClass.variable);
        //System.out.println(Integer.staticVariable);
        //System.out.println(Integer.variable);

        StaticInnerClass sic = new StaticInnerClass();

        // cannot be referenced from a static context
        //InnerClass ic = new InnerClass();
    }

    public void normalFunction(){
        StaticInnerClass sic = new StaticInnerClass();
        InnerClass ic = new InnerClass();
    }

    //4.静态内部类
    // 我们对嵌套类使用static关键字。
    // static不能用于最外层的类。
    // 静态的嵌套类和其它外层的类别无二致，嵌套只是为了方便打包。
    //  1、只有内部类才能声明为static，也可以说是静态内部类
    //  2、只有静态内部类才能拥有静态成员，普通内部类只能定义普通成员
    //  3、静态类跟静态方法一样，只能访问其外部类的静态成员
    //  4、如果在外部类的静态方法中访问内部类，这时候只能访问静态内部类
    public static class  StaticInnerClass{
        private static String staticVariable = "staticVariable";
        private String variable = "variable";

        public StaticInnerClass() {
            // non-static field 'outerVariable' cannot be referenced from a static context(不能访问其外部类的非静态成员)
            // System.out.println(outerVariable);
            System.out.println(outerStaticVariable);
        }
    }

    //内部类
    //1、内部类拥有普通类的所有特性，也拥有类成员变量的特性
    //2、内部类可以访问其外部类的成员变量，属性，方法，其它内部类
    public class  InnerClass{
        // Inner classes cannot have static declarations(不能定义静态成员)
        // private static String staticVariable = "staticVariable";
        private String variable = "variable";

        // 可以访问外部类静态与非静态成员
        public InnerClass() {
            System.out.println(outerVariable);
            System.out.println(outerStaticVariable);
        }
    }
}

class OuterClassDemo{
    public static void main(String[] args) {

        /**
         * 1：其它类访问内部类，必须使用：外部类.内部类，OutClass.InnerClass
         * 2：普通内部类必须绑定在其外部类的实例上
         * 3：静态内部类可以直接 new
         */


        StaticInnerClassDemo.StaticInnerClass staticInnerClass = new StaticInnerClassDemo.StaticInnerClass();
        StaticInnerClassDemo staticInnerClassDemo = new StaticInnerClassDemo();
        StaticInnerClassDemo.InnerClass ic = new StaticInnerClassDemo().new InnerClass();

        //StaticInnerClassDemo is not an enclosing class(不是封闭类，)
        //StaticInnerClassDemo.InnerClass ic2 = new StaticInnerClassDemo.InnerClass();
    }
}
